home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i010: RCS source control system, Part10/12
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 1d181017 1c0fdd37 3174ca6e 201ae133
-
- Submitted-by: Adam Hammer <hammer@cs.purdue.edu>
- Posting-number: Volume 24, Issue 10
- Archive-name: rcs/part10
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: man/rcsintro.1 rcs_func.ms src/maketime.c src/rcsdiff.c
- # src/rcskeep.c src/rcsmerge.c
- # Wrapped by rsalz@litchi.bbn.com on Thu Feb 21 14:37:09 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 10 (of 12)."'
- if test -f 'man/rcsintro.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'man/rcsintro.1'\"
- else
- echo shar: Extracting \"'man/rcsintro.1'\" \(9209 characters\)
- sed "s/^X//" >'man/rcsintro.1' <<'END_OF_FILE'
- X.de Id
- X.ds Rv \\$3
- X.ds Dt \\$4
- X..
- X.Id $Id: rcsintro.1,v 5.0 1990/08/22 09:11:00 eggert Exp $
- X.ds r \s-1RCS\s0
- X.if n .ds - \%--
- X.if t .ds - \(em
- X.am SS
- X.LP
- X..
- X.TH RCSINTRO 1 \*(Dt GNU
- X.SH NAME
- Xrcsintro \- introduction to RCS commands
- X.SH DESCRIPTION
- XThe Revision Control System (\*r) manages multiple revisions of files.
- X\*r automates the storing, retrieval, logging, identification, and merging
- Xof revisions. \*r is useful for text that is revised frequently, for example
- Xprograms, documentation, graphics, papers, and form letters.
- X.PP
- XThe basic user interface is extremely simple. The novice only needs
- Xto learn two commands:
- X.BR ci (1)
- Xand
- X.BR co (1).
- X.BR ci ,
- Xshort for \*(lqcheck in\*(rq, deposits the contents of a
- Xfile into an archival file called an \*r file. An \*r file
- Xcontains all revisions of a particular file.
- X.BR co ,
- Xshort for \*(lqcheck out\*(rq, retrieves revisions from an \*r file.
- X.SS "Functions of \*r"
- X.IP \(bu
- XStore and retrieve multiple revisions of text. \*r saves all old
- Xrevisions in a space efficient way.
- XChanges no longer destroy the original, because the
- Xprevious revisions remain accessible. Revisions can be retrieved according to
- Xranges of revision numbers, symbolic names, dates, authors, and
- Xstates.
- X.IP \(bu
- XMaintain a complete history of changes.
- X\*r logs all changes automatically.
- XBesides the text of each revision, \*r stores the author, the date and time of
- Xcheck-in, and a log message summarizing the change.
- XThe logging makes it easy to find out
- Xwhat happened to a module, without having to compare
- Xsource listings or having to track down colleagues.
- X.IP \(bu
- XResolve access conflicts. When two or more programmers wish to
- Xmodify the same revision, \*r alerts the programmers and prevents one
- Xmodification from corrupting the other.
- X.IP \(bu
- XMaintain a tree of revisions. \*r can maintain separate lines of development
- Xfor each module. It stores a tree structure that represents the
- Xancestral relationships among revisions.
- X.IP \(bu
- XMerge revisions and resolve conflicts.
- XTwo separate lines of development of a module can be coalesced by merging.
- XIf the revisions to be merged affect the same sections of code, \*r alerts the
- Xuser about the overlapping changes.
- X.IP \(bu
- XControl releases and configurations.
- XRevisions can be assigned symbolic names
- Xand marked as released, stable, experimental, etc.
- XWith these facilities, configurations of modules can be
- Xdescribed simply and directly.
- X.IP \(bu
- XAutomatically identify each revision with name, revision number,
- Xcreation time, author, etc.
- XThe identification is like a stamp that can be embedded at an appropriate place
- Xin the text of a revision.
- XThe identification makes it simple to determine which
- Xrevisions of which modules make up a given configuration.
- X.IP \(bu
- XMinimize secondary storage. \*r needs little extra space for
- Xthe revisions (only the differences). If intermediate revisions are
- Xdeleted, the corresponding deltas are compressed accordingly.
- X.SS "Getting Started with \*r"
- XSuppose you have a file
- X.B f.c
- Xthat you wish to put under control of \*r.
- XInvoke the check-in command
- X.IP
- X.B "ci f.c"
- X.LP
- XThis command creates the \*r file
- X.BR f.c,v ,
- Xstores
- X.B f.c
- Xinto it as revision 1.1, and
- Xdeletes
- X.BR f.c .
- XIt also asks you for a description. The description
- Xshould be a synopsis of the contents of the file. All later check-in
- Xcommands will ask you for a log entry, which should summarize the
- Xchanges that you made.
- X.PP
- XFiles ending in
- X.B ,v
- Xare called \*r files (\*(lqv\*(rq stands for \*(lqversions\*(rq);
- Xthe others are called working files.
- XTo get back the working file
- X.B f.c
- Xin the previous example, use the check-out
- Xcommand
- X.IP
- X.B "co f.c"
- X.LP
- XThis command extracts the latest revision from
- X.B f.c,v
- Xand writes
- Xit into
- X.BR f.c .
- XIf you want to edit
- X.BR f.c ,
- Xyou must lock it as you check it out with the command
- X.IP
- X.B "co \-l f.c"
- X.LP
- XYou can now edit
- X.BR f.c .
- X.PP
- XSuppose after some editing you want to know what changes that you have made.
- XThe command
- X.IP
- X.B "rcsdiff f.c"
- X.LP
- Xtells you the difference between the most recently checked-in version
- Xand the working file.
- XYou can check the file back in by invoking
- X.IP
- X.B "ci f.c"
- X.LP
- XThis increments the revision number properly.
- X.PP
- XIf
- X.B ci
- Xcomplains with the message
- X.IP
- X.BI "ci error: no lock set by " "your name"
- X.LP
- Xthen you have tried to check in a file even though you did not
- Xlock it when you checked it out.
- XOf course, it is too late now to do the check-out with locking, because
- Xanother check-out would
- Xoverwrite your modifications. Instead, invoke
- X.IP
- X.B "rcs \-l f.c"
- X.LP
- XThis command will lock the latest revision for you, unless somebody
- Xelse got ahead of you already. In this case, you'll have to negotiate with
- Xthat person.
- X.PP
- XLocking assures that you, and only you, can check in the next update, and
- Xavoids nasty problems if several people work on the same file.
- XEven if a revision is locked, it can still be checked out for
- Xreading, compiling, etc. All that locking
- Xprevents is a
- X.I "check-in"
- Xby anybody but the locker.
- X.PP
- XIf your \*r file is private, i.e., if you are the only person who is going
- Xto deposit revisions into it, strict locking is not needed and you
- Xcan turn it off.
- XIf strict locking is turned off,
- Xthe owner of the \*r file need not have a lock for check-in; all others
- Xstill do. Turning strict locking off and on is done with the commands
- X.IP
- X.BR "rcs \-U f.c" " and " "rcs \-L f.c"
- X.LP
- XIf you don't want to clutter your working directory with \*r files, create
- Xa subdirectory called
- X.B RCS
- Xin your working directory, and move all your \*r
- Xfiles there. \*r commands will look first into that directory to find
- Xneeded files. All the commands discussed above will still work, without any
- Xmodification.
- X(Actually, pairs of \*r and working files can be specified in three ways:
- X(a) both are given, (b) only the working file is given, (c) only the
- X\*r file is given. Both \*r and working files may have arbitrary path prefixes;
- X\*r commands pair them up intelligently.)
- X.PP
- XTo avoid the deletion of the working file during check-in (in case you want to
- Xcontinue editing or compiling), invoke
- X.IP
- X.BR "ci \-l f.c" " or " "ci \-u f.c"
- X.LP
- XThese commands check in
- X.B f.c
- Xas usual, but perform an implicit
- Xcheck-out. The first form also locks the checked in revision, the second one
- Xdoesn't. Thus, these options save you one check-out operation.
- XThe first form is useful if you want to continue editing,
- Xthe second one if you just want to read the file.
- XBoth update the identification markers in your working file (see below).
- X.PP
- XYou can give
- X.B ci
- Xthe number you want assigned to a checked in
- Xrevision. Assume all your revisions were numbered 1.1, 1.2, 1.3, etc.,
- Xand you would like to start release 2.
- XThe command
- X.IP
- X.BR "ci \-r2 f.c" " or " "ci \-r2.1 f.c"
- X.LP
- Xassigns the number 2.1 to the new revision.
- XFrom then on,
- X.B ci
- Xwill number the subsequent revisions
- Xwith 2.2, 2.3, etc. The corresponding
- X.B co
- Xcommands
- X.IP
- X.BR "co \-r2 f.c" " and " "co \-r2.1 f.c"
- X.PP
- Xretrieve the latest revision numbered
- X.RI 2. x
- Xand the revision 2.1,
- Xrespectively.
- X.B co
- Xwithout a revision number selects
- Xthe latest revision on the
- X.IR trunk ,
- Xi.e. the highest
- Xrevision with a number consisting of two fields. Numbers with more than two
- Xfields are needed for branches.
- XFor example, to start a branch at revision 1.3, invoke
- X.IP
- X.B "ci \-r1.3.1 f.c"
- X.LP
- XThis command starts a branch numbered 1 at revision 1.3, and assigns
- Xthe number 1.3.1.1 to the new revision. For more information about
- Xbranches, see
- X.BR rcsfile (5).
- X.SS "Automatic Identification"
- X\*r can put special strings for identification into your source and object
- Xcode. To obtain such identification, place the marker
- X.IP
- X.B "$\&Id$"
- X.LP
- Xinto your text, for instance inside a comment.
- X\*r will replace this marker with a string of the form
- X.IP
- X.BI $\&Id: " filename revision date time author state " $
- X.LP
- XWith such a marker on the first page of each module, you can
- Xalways see with which revision you are working.
- X\*r keeps the markers up to date automatically.
- XTo propagate the markers into your object code, simply put
- Xthem into literal character strings. In C, this is done as follows:
- X.IP
- X.ft 3
- Xstatic char rcsid[] = \&"$\&Id$\&";
- X.ft
- X.LP
- XThe command
- X.B ident
- Xextracts such markers from any file, even object code
- Xand dumps.
- XThus,
- X.B ident
- Xlets you find out
- Xwhich revisions of which modules were used in a given program.
- X.PP
- XYou may also find it useful to put the marker
- X.B $\&Log$
- Xinto your text, inside a comment. This marker accumulates
- Xthe log messages that are requested during check-in.
- XThus, you can maintain the complete history of your file directly inside it.
- XThere are several additional identification markers; see
- X.BR co (1)
- Xfor
- Xdetails.
- X.SH IDENTIFICATION
- XAuthor: Walter F. Tichy.
- X.br
- XRevision Number: \*(Rv; Release Date: \*(Dt.
- X.br
- XCopyright \(co 1982, 1988, 1989 by Walter F. Tichy.
- X.br
- XCopyright \(co 1990 by Paul Eggert.
- X.SH "SEE ALSO"
- Xci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1)
- X.br
- XWalter F. Tichy,
- X\*r\*-A System for Version Control,
- X.I "Software\*-Practice & Experience"
- X.BR 15 ,
- X7 (July 1985), 637-654.
- END_OF_FILE
- if test 9209 -ne `wc -c <'man/rcsintro.1'`; then
- echo shar: \"'man/rcsintro.1'\" unpacked with wrong size!
- fi
- # end of 'man/rcsintro.1'
- fi
- if test -f 'rcs_func.ms' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rcs_func.ms'\"
- else
- echo shar: Extracting \"'rcs_func.ms'\" \(3683 characters\)
- sed "s/^X//" >'rcs_func.ms' <<'END_OF_FILE'
- X.SH
- XFunctions of RCS (Revision Control System)
- X.PP
- XRCS manages software libraries. It greatly increases programmer productivity
- Xby providing the following functions.
- X.IP 1.
- XRCS stores and retrieves multiple revisions of program and other text.
- XThus, one can maintain one or more releases while developing the next
- Xrelease, with a minimum of space overhead. Changes no longer destroy the
- Xoriginal -- previous revisions remain accessible.
- X.RS
- X.IP a.
- XMaintains each module as a tree of revisions.
- X.IP b.
- XProject libraries can
- Xbe organized centrally, decentralized, or any way you like.
- X.IP c.
- XRCS works for any type of text: programs, documentation, memos, papers,
- Xgraphics, VLSI layouts, form letters, etc.
- X.RE
- X.IP 2.
- XRCS maintains a complete history of changes.
- XThus, one can find out what happened to a module easily
- Xand quickly, without having to compare source listings or
- Xhaving to track down colleagues.
- X.RS
- X.IP a.
- XRCS performs automatic record keeping.
- X.IP b.
- XRCS logs all changes automatically.
- X.IP c.
- XRCS guarantees project continuity.
- X.RE
- X.IP 3.
- XRCS manages multiple lines of development.
- X.IP 4.
- XRCS can merge multiple lines of development.
- XThus, when several parallel lines of development must be consolidated
- Xinto one line, the merging of changes is automatic.
- X.IP 5.
- XRCS flags coding conflicts.
- XIf two or more lines of development modify the same section of code,
- XRCS can alert programmers about overlapping changes.
- X.IP 6.
- XRCS resolves access conflicts.
- XWhen two or more programmers wish to modify the same revision,
- XRCS alerts the programmers and makes sure that one modification won't wipe
- Xout the other one.
- X.IP 7.
- XRCS provides high-level retrieval functions.
- XRevisions can be retrieved according to ranges of revision numbers,
- Xsymbolic names, dates, authors, and states.
- X.IP 8.
- XRCS provides release and configuration control.
- XRevisions can be marked as released, stable, experimental, etc.
- XConfigurations of modules can be described simply and directly.
- X.IP 9.
- XRCS performs automatic identification of modules with name, revision
- Xnumber, creation time, author, etc.
- XThus, it is always possible to determine which revisions of which
- Xmodules make up a given configuration.
- X.IP 10.
- XProvides high-level management visibility.
- XThus, it is easy to track the status of a software project.
- X.RS
- X.IP a.
- XRCS provides a complete change history.
- X.IP b.
- XRCS records who did what when to which revision of which module.
- X.RE
- X.IP 11.
- XRCS is fully compatible with existing software development tools.
- XRCS is unobtrusive -- its interface to the file system is such that
- Xall your existing software tools can be used as before.
- X.IP 12.
- XRCS' basic user interface is extremely simple. The novice need to learn
- Xonly two commands. Its more sophisticated features have been
- Xtuned towards advanced software development environments and the
- Xexperienced software professional.
- X.IP 13.
- XRCS simplifies software distribution if customers
- Xmaintain sources with RCS also. This technique assures proper
- Xidentification of versions and configurations, and tracking of customer
- Xmodifications. Customer modifications can be merged into distributed
- Xversions locally or by the development group.
- X.IP 14.
- XRCS needs little extra space for the revisions (only the differences).
- XIf intermediate revisions are deleted, the corresponding
- Xdifferences are compressed into the shortest possible form.
- X.IP 15.
- XRCS is implemented with reverse deltas. This means that
- Xthe latest revision, which is the one that is accessed most often,
- Xis stored intact. All others are regenerated from the latest one
- Xby applying reverse deltas (backward differences). This
- Xresults in fast access time for the revision needed most often.
- END_OF_FILE
- if test 3683 -ne `wc -c <'rcs_func.ms'`; then
- echo shar: \"'rcs_func.ms'\" unpacked with wrong size!
- fi
- # end of 'rcs_func.ms'
- fi
- if test -f 'src/maketime.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/maketime.c'\"
- else
- echo shar: Extracting \"'src/maketime.c'\" \(8733 characters\)
- sed "s/^X//" >'src/maketime.c' <<'END_OF_FILE'
- X#
- X/*
- X * MAKETIME derive 32-bit time value from TM structure.
- X *
- X * Usage:
- X * int zone; Minutes west of GMT, or
- X * 48*60 for localtime
- X * time_t t;
- X * struct tm *tp; Pointer to TM structure from <time.h>
- X * t = maketime(tp,zone);
- X *
- X * Returns:
- X * -1 if failure; parameter out of range or nonsensical.
- X * else time-value.
- X * Notes:
- X * This code is quasi-public; it may be used freely in like software.
- X * It is not to be sold, nor used in licensed software without
- X * permission of the author.
- X * For everyone's benefit, please report bugs and improvements!
- X * Copyright 1981 by Ken Harrenstien, SRI International.
- X * (ARPANET: KLH @ SRI)
- X */
- X/* $Log: maketime.c,v $
- X * Revision 5.2 1990/11/01 05:03:30 eggert
- X * Remove lint.
- X *
- X * Revision 5.1 1990/10/04 06:30:13 eggert
- X * Calculate the GMT offset of 'xxx LT' as of xxx, not as of now.
- X * Don't assume time_t is 32 bits. Fix bugs near epoch and near end of time.
- X *
- X * Revision 5.0 1990/08/22 08:12:38 eggert
- X * Switch to GMT and fix the bugs exposed thereby.
- X * Permit dates past 1999/12/31. Ansify and Posixate.
- X *
- X * Revision 1.8 88/11/08 13:54:53 narten
- X * allow negative timezones (-24h <= x <= 24h)
- X *
- X * Revision 1.7 88/08/28 14:47:52 eggert
- X * Allow cc -R. Remove unportable "#endif XXX"s.
- X *
- X * Revision 1.6 87/12/18 17:05:58 narten
- X * include rcsparam.h
- X *
- X * Revision 1.5 87/12/18 11:35:51 narten
- X * maketime.c: fixed USG code - you have tgo call "tzset" in order to have
- X * "timezone" set. ("localtime" calls it, but it's probably better not to
- X * count on "localtime" having been called.)
- X *
- X * Revision 1.4 87/10/18 10:26:57 narten
- X * Updating version numbers. Changes relative to 1.0 are actually
- X * relative to 1.2
- X *
- X * Revision 1.3 87/09/24 13:58:45 narten
- X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- X * warnings)
- X *
- X * Revision 1.2 87/03/27 14:21:48 jenkins
- X * Port to suns
- X *
- X * Revision 1.2 83/12/05 10:12:56 wft
- X * added cond. compilation for USG Unix; long timezone;
- X *
- X * Revision 1.1 82/05/06 11:38:00 wft
- X * Initial revision
- X *
- X */
- X
- X
- X#include "rcsbase.h"
- X
- XlibId(maketId, "$Id: maketime.c,v 5.2 1990/11/01 05:03:30 eggert Exp $")
- X
- Xstatic const struct tm *time2tm P((time_t));
- X
- X#define given(v) (0 <= (v)) /* Negative values are unspecified. */
- X
- Xstatic const int daytb[] = {
- X /* # days in year thus far, indexed by month (0-12!!) */
- X 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
- X};
- X
- X static time_t
- Xmaketime(atm,zone)
- X const struct tm *atm;
- X int zone;
- X{
- X register const struct tm *tp;
- X register int i;
- X int year, yday, mon, day, hour, min, sec, leap, localzone;
- X int attempts;
- X time_t t, tres;
- X
- X attempts = 2;
- X localzone = zone==48*60;
- X tres = -1;
- X year = mon = day = 0; /* Keep lint happy. */
- X
- X do {
- X
- X if (localzone || !given(atm->tm_year)) {
- X if (tres == -1)
- X if ((tres = time((time_t*)0)) == -1)
- X return -1;
- X tp = time2tm(tres);
- X /* Get breakdowns of default time, adjusting to zone. */
- X year = tp->tm_year; /* Use to set up defaults */
- X yday = tp->tm_yday;
- X mon = tp->tm_mon;
- X day = tp->tm_mday;
- X hour = tp->tm_hour;
- X min = tp->tm_min;
- X if (localzone) {
- X tp = localtime(&tres);
- X zone =
- X min - tp->tm_min + 60*(
- X hour - tp->tm_hour + 24*(
- X /* If years differ, it's by one day. */
- X year - tp->tm_year
- X ? year - tp->tm_year
- X : yday - tp->tm_yday));
- X }
- X /* Adjust the default day, month and year according to zone. */
- X if ((min -= zone) < 0) {
- X if (hour-(59-min)/60 < 0 && --day <= 0) {
- X if (--mon < 0) {
- X --year;
- X mon = 11;
- X }
- X day = daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3));
- X }
- X } else
- X if (
- X 24 <= hour+min/60 &&
- X daytb[mon+1] - daytb[mon] + (mon==1&&!(year&3)) < ++day
- X ) {
- X if (11 < ++mon) {
- X ++year;
- X mon = 0;
- X }
- X day = 1;
- X }
- X }
- X if (zone < -24*60 || 24*60 < zone)
- X return -1;
- X
- X
- X#ifdef DEBUG
- Xprintf("first YMD: %d %d %d\n",year,mon,day);
- X#endif
- X tp = atm;
- X
- X /* First must find date, using specified year, month, day.
- X * If one of these is unspecified, it defaults either to the
- X * current date (if no more global spec was given) or to the
- X * zero-value for that spec (i.e. a more global spec was seen).
- X * Reject times that do not fit in time_t,
- X * without assuming that time_t is 32 bits or is signed.
- X */
- X if (given(tp->tm_year))
- X {
- X year = tp->tm_year;
- X mon = 0; /* Since year was given, default */
- X day = 1; /* for remaining specs is zero */
- X }
- X if (year < 69) /* 1969/12/31 OK in some timezones. */
- X return -1; /* ERR: year out of range */
- X leap = !(year&3) && (year%100 || !((year+300)%400));
- X year -= 70; /* UNIX time starts at 1970 */
- X
- X /*
- X * Find day of year.
- X */
- X {
- X if (given(tp->tm_mon))
- X { mon = tp->tm_mon; /* Month was specified */
- X day = 1; /* so set remaining default */
- X }
- X if (11 < (unsigned)mon)
- X return -1; /* ERR: bad month */
- X if (given(tp->tm_mday)) day = tp->tm_mday;
- X if(day < 1
- X || (((daytb[mon+1]-daytb[mon]) < day)
- X && (day!=29 || mon!=1 || !leap) ))
- X return -1; /* ERR: bad day */
- X yday = daytb[mon] /* Add # of days in months so far */
- X + ((leap /* Leap year, and past Feb? If */
- X && mon>1)? 1:0) /* so, add leap day for this year */
- X + day-1; /* And finally add # days this mon */
- X
- X }
- X if (leap+365 <= (unsigned)yday)
- X return -1; /* ERR: bad YDAY */
- X
- X if (year < 0) {
- X if (yday != 364)
- X return -1; /* ERR: too early */
- X t = -1;
- X } else {
- X tres = year*365; /* Get # days of years so far */
- X if (tres/365 != year)
- X return -1; /* ERR: overflow */
- X t = tres
- X + ((year+1)>>2) /* plus # of leap days since 1970 */
- X + yday; /* and finally add # days this year */
- X if (t+4 < tres)
- X return -1; /* ERR: overflow */
- X }
- X tres = t;
- X
- X if (given(i = tp->tm_wday)) /* Check WDAY if present */
- X if (i != (tres+4)%7) /* 1970/01/01 was Thu = 4 */
- X return -1; /* ERR: bad WDAY */
- X
- X#ifdef DEBUG
- Xprintf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
- X#endif
- X /*
- X * Now determine time. If not given, default to zeros
- X * (since time is always the least global spec)
- X */
- X tres *= 86400L; /* Get # seconds (24*60*60) */
- X if (tres/86400L != t)
- X return -1; /* ERR: overflow */
- X hour = min = sec = 0;
- X if (given(tp->tm_hour)) hour = tp->tm_hour;
- X if (given(tp->tm_min )) min = tp->tm_min;
- X if (given(tp->tm_sec )) sec = tp->tm_sec;
- X if (60 <= (unsigned)min || 60 < (unsigned)sec)
- X return -1; /* ERR: MS out of range */
- X if (24 <= (unsigned)hour)
- X if(hour != 24 || (min+sec) !=0) /* Allow 24:00 */
- X return -1; /* ERR: H out of range */
- X
- X t = tres;
- X tres += sec + 60L*(zone + min + 60*hour);
- X
- X#ifdef DEBUG
- Xprintf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres);
- X#endif
- X
- X if (!localzone) /* check for overflow */
- X return (year<0 ? (tres<0||86400L<=tres) : tres<t) ? -1 : tres;
- X
- X /* Check results; LT may have had a different GMT offset back then. */
- X tp = localtime(&tres);
- X if (given(atm->tm_sec) && atm->tm_sec != tp->tm_sec)
- X return -1; /* If seconds don't match, we're in trouble. */
- X if (!(
- X given(atm->tm_min) && atm->tm_min != tp->tm_min ||
- X given(atm->tm_hour) && atm->tm_hour != tp->tm_hour ||
- X given(atm->tm_mday) && atm->tm_mday != tp->tm_mday ||
- X given(atm->tm_mon) && atm->tm_mon != tp->tm_mon ||
- X given(atm->tm_year) && atm->tm_year != tp->tm_year
- X ))
- X return tres; /* Everything matches. */
- X
- X } while (--attempts);
- X
- X return -1;
- X}
- X
- X/*
- X* Convert Unix time to struct tm format.
- X* Use Coordinated Universal Time (UTC) if available and if version 5 or newer;
- X* use local time otherwise.
- X*/
- X static const struct tm *
- Xtime2tm(unixtime)
- X time_t unixtime;
- X{
- X const struct tm *tm;
- X return
- X VERSION(5)<=RCSversion && (tm = gmtime(&unixtime))
- X ? tm
- X : localtime(&unixtime);
- X}
- X
- X/*
- X* Convert Unix time to RCS format.
- X* For compatibility with older versions of RCS,
- X* dates before AD 2000 are stored without the leading "19".
- X*/
- X void
- Xtime2date(unixtime,date)
- X time_t unixtime;
- X char date[datesize];
- X{
- X register const struct tm *tm = time2tm(unixtime);
- X VOID sprintf(date, DATEFORM,
- X tm->tm_year + (tm->tm_year<100 ? 0 : 1900),
- X tm->tm_mon+1, tm->tm_mday,
- X tm->tm_hour, tm->tm_min, tm->tm_sec
- X );
- X}
- X
- X
- X
- X void
- Xstr2date(source, target)
- X const char *source;
- X char target[datesize];
- X/* Parse a free-format date in SOURCE, convert it
- X * into RCS internal format, and store the result into TARGET.
- X */
- X{
- X int zone;
- X time_t unixtime;
- X struct tm parseddate;
- X
- X if (!partime(source, &parseddate, &zone))
- X faterror("can't parse date/time: %s", source);
- X if ((unixtime = maketime(&parseddate, zone)) == -1)
- X faterror("bad date/time: %s", source);
- X time2date(unixtime, target);
- X}
- END_OF_FILE
- if test 8733 -ne `wc -c <'src/maketime.c'`; then
- echo shar: \"'src/maketime.c'\" unpacked with wrong size!
- fi
- # end of 'src/maketime.c'
- fi
- if test -f 'src/rcsdiff.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/rcsdiff.c'\"
- else
- echo shar: Extracting \"'src/rcsdiff.c'\" \(10976 characters\)
- sed "s/^X//" >'src/rcsdiff.c' <<'END_OF_FILE'
- X/*
- X * RCS rcsdiff operation
- X */
- X/*****************************************************************************
- X * generate difference between RCS revisions
- X *****************************************************************************
- X */
- X
- X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- X Copyright 1990 by Paul Eggert
- X Distributed under license by the Free Software Foundation, Inc.
- X
- XThis file is part of RCS.
- X
- XRCS is free software; you can redistribute it and/or modify
- Xit under the terms of the GNU General Public License as published by
- Xthe Free Software Foundation; either version 1, or (at your option)
- Xany later version.
- X
- XRCS is distributed in the hope that it will be useful,
- Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
- XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- XGNU General Public License for more details.
- X
- XYou should have received a copy of the GNU General Public License
- Xalong with RCS; see the file COPYING. If not, write to
- Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- X
- XReport problems and direct all questions to:
- X
- X rcs-bugs@cs.purdue.edu
- X
- X*/
- X
- X
- X
- X
- X/* $Log: rcsdiff.c,v $
- X * Revision 5.7 1990/12/13 06:54:07 eggert
- X * GNU diff 1.15 has -u.
- X *
- X * Revision 5.6 1990/11/01 05:03:39 eggert
- X * Remove unneeded setid check.
- X *
- X * Revision 5.5 1990/10/04 06:30:19 eggert
- X * Accumulate exit status across files.
- X *
- X * Revision 5.4 1990/09/27 01:31:43 eggert
- X * Yield 1, not EXIT_FAILURE, when diffs are found.
- X *
- X * Revision 5.3 1990/09/11 02:41:11 eggert
- X * Simplify -kkvl test.
- X *
- X * Revision 5.2 1990/09/04 17:07:19 eggert
- X * Diff's argv was too small by 1.
- X *
- X * Revision 5.1 1990/08/29 07:13:55 eggert
- X * Add -kkvl.
- X *
- X * Revision 5.0 1990/08/22 08:12:46 eggert
- X * Add -k, -V. Don't use access(). Add setuid support.
- X * Remove compile-time limits; use malloc instead.
- X * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
- X * Add GNU diff's flags. Make lock and temp files faster and safer.
- X * Ansify and Posixate.
- X *
- X * Revision 4.6 89/05/01 15:12:27 narten
- X * changed copyright header to reflect current distribution rules
- X *
- X * Revision 4.5 88/08/09 19:12:41 eggert
- X * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
- X *
- X * Revision 4.4 87/12/18 11:37:46 narten
- X * changes Jay Lepreau made in the 4.3 BSD version, to add support for
- X * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
- X * merged in.
- X *
- X * Revision 4.3 87/10/18 10:31:42 narten
- X * Updating version numbers. Changes relative to 1.1 actually
- X * relative to 4.1
- X *
- X * Revision 1.3 87/09/24 13:59:21 narten
- X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- X * warnings)
- X *
- X * Revision 1.2 87/03/27 14:22:15 jenkins
- X * Port to suns
- X *
- X * Revision 4.1 83/05/03 22:13:19 wft
- X * Added default branch, option -q, exit status like diff.
- X * Added fterror() to replace faterror().
- X *
- X * Revision 3.6 83/01/15 17:52:40 wft
- X * Expanded mainprogram to handle multiple RCS files.
- X *
- X * Revision 3.5 83/01/06 09:33:45 wft
- X * Fixed passing of -c (context) option to diff.
- X *
- X * Revision 3.4 82/12/24 15:28:38 wft
- X * Added call to catchsig().
- X *
- X * Revision 3.3 82/12/10 16:08:17 wft
- X * Corrected checking of return code from diff; improved error msgs.
- X *
- X * Revision 3.2 82/12/04 13:20:09 wft
- X * replaced getdelta() with gettree(). Changed diagnostics.
- X *
- X * Revision 3.1 82/11/28 19:25:04 wft
- X * Initial revision.
- X *
- X */
- X#include "rcsbase.h"
- X
- X#if DIFF_L
- Xstatic const char *setup_label P((struct buf*,const char*,const char[datesize]));
- X#endif
- Xstatic void cleanup P((void));
- X
- Xstatic const char co[] = CO;
- X
- Xstatic int exitstatus;
- X
- XmainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 5.7 1990/12/13 06:54:07 eggert Exp $")
- X{
- X static const char cmdusage[] =
- X "\nrcsdiff usage: rcsdiff [-q] [-rrev1 [-rrev2]] [-Vn] [diff options] file ...";
- X static const char quietarg[] = "-q";
- X
- X int revnums; /* counter for revision numbers given */
- X const char *rev1, *rev2; /* revision numbers from command line */
- X const char *xrev1, *xrev2; /* expanded revision numbers */
- X const char *expandarg, *lexpandarg, *versionarg;
- X#if DIFF_L
- X static struct buf labelbuf[2];
- X int file_labels;
- X const char **diff_label1, **diff_label2;
- X char date2[datesize];
- X#endif
- X const char **diffv, **diffp; /* argv for subsidiary diff */
- X const char **pp, *p, *diffvstr;
- X struct buf commarg;
- X struct buf numericrev; /* expanded revision number */
- X struct hshentries *gendeltas; /* deltas to be generated */
- X struct hshentry * target;
- X int exit_stats;
- X char *argp, *dcp;
- X register c;
- X
- X initid();
- X catchints();
- X
- X bufautobegin(&commarg);
- X bufautobegin(&numericrev);
- X revnums = 0;
- X rev1 = rev2 = xrev2 = nil;
- X#if DIFF_L
- X file_labels = 0;
- X#endif
- X expandarg = versionarg = quietarg; /* i.e. a no-op */
- X
- X /* Room for args + 2 i/o [+ 2 labels] + 1 file + 1 trailing null. */
- X diffp = diffv = tnalloc(const char*, argc + 4 + 2*DIFF_L);
- X *diffp++ = nil;
- X *diffp++ = nil;
- X *diffp++ = DIFF;
- X
- X while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
- X dcp = argp = *argv + 1;
- X while (c = *argp++) switch (c) {
- X case 'r':
- X if (*argp!='\0') {
- X if (revnums==0) {
- X rev1= argp; revnums=1;
- X } else if (revnums==1) {
- X rev2= argp; revnums=2;
- X } else {
- X faterror("too many revision numbers");
- X }
- X } /* do nothing for empty -r */
- X goto option_handled;
- X#if DIFF_L
- X case 'L':
- X if (++file_labels == 2)
- X faterror("too many -L options");
- X /* fall into */
- X#endif
- X case 'C': case 'D': case 'F': case 'I':
- X *dcp++ = c;
- X if (*argp)
- X do *dcp++ = *argp;
- X while (*++argp);
- X else {
- X if (!--argc)
- X faterror("-%c needs following argument%s",
- X c, cmdusage
- X );
- X *diffp++ = *argv++;
- X }
- X break;
- X case 'B': case 'H': case 'T':
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- X case 'h': case 'i': case 'n': case 'p':
- X case 't': case 'u': case 'w':
- X *dcp++ = c;
- X break;
- X case 'q':
- X quietflag=true;
- X break;
- X case 'V':
- X versionarg = *argv;
- X setRCSversion(versionarg);
- X goto option_handled;
- X case 'k':
- X expandarg = *argv;
- X if (0 <= str2expmode(expandarg+2))
- X goto option_handled;
- X /* fall into */
- X default:
- X faterror("unknown option: %s%s", *argv, cmdusage);
- X };
- X option_handled:
- X if (dcp != *argv+1) {
- X *dcp = 0;
- X *diffp++ = *argv;
- X }
- X } /* end of option processing */
- X
- X if (argc<1) faterror("no input file%s", cmdusage);
- X
- X for (pp = diffv+3, c = 0; pp<diffp; )
- X c += strlen(*pp++) + 1;
- X diffvstr = argp = tnalloc(char, c + 1);
- X for (pp = diffv+3; pp<diffp; ) {
- X p = *pp++;
- X *argp++ = ' ';
- X while ((*argp = *p++))
- X argp++;
- X }
- X *argp = 0;
- X
- X#if DIFF_L
- X diff_label1 = diff_label2 = nil;
- X if (file_labels < 2) {
- X if (!file_labels)
- X diff_label1 = diffp++;
- X diff_label2 = diffp++;
- X }
- X#endif
- X diffp[2] = nil;
- X
- X /* now handle all filenames */
- X do {
- X finptr=NULL;
- X ffree();
- X
- X if (pairfilenames(argc, argv, rcsreadopen, true, false) != 1)
- X continue;
- X diagnose("===================================================================\nRCS file: %s\n",RCSfilename);
- X if (!rev2) {
- X /* Make sure work file is readable, and get its status. */
- X if ((c = open(workfilename,O_RDONLY,0)) < 0) {
- X eerror(workfilename);
- X continue;
- X }
- X if (!getfworkstat(c)) continue;
- X VOID close(c);
- X }
- X
- X
- X gettree(); /* reads in the delta tree */
- X
- X if (Head==nil) {
- X error("no revisions present");
- X continue;
- X }
- X if (revnums==0)
- X rev1 = Dbranch ? Dbranch : Head->num;
- X
- X if (!expandsym(rev1,&numericrev)) continue;
- X if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue;
- X xrev1=target->num;
- X#if DIFF_L
- X if (diff_label1)
- X *diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
- X#endif
- X
- X lexpandarg = expandarg;
- X if (revnums==2) {
- X if (!expandsym(rev2, &numericrev)) continue;
- X if (!(target=genrevs(numericrev.string,(char *)nil,(char *)nil,(char *)nil,&gendeltas))) continue;
- X xrev2=target->num;
- X } else if (
- X target->lockedby
- X && lexpandarg == quietarg
- X && Expand == KEYVAL_EXPAND
- X && WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
- X )
- X lexpandarg = "-kkvl";
- X#if DIFF_L
- X if (diff_label2)
- X if (revnums == 2)
- X *diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
- X else {
- X time2date(workstat.st_mtime, date2);
- X *diff_label2 = setup_label(&labelbuf[1], workfilename, date2);
- X }
- X#endif
- X
- X diffp[0] = maketemp(0);
- X diagnose("retrieving revision %s\n", xrev1);
- X bufscpy(&commarg, "-p");
- X bufscat(&commarg, xrev1);
- X if (run((char*)nil,diffp[0], co,quietarg,commarg.string,lexpandarg,versionarg,RCSfilename,(char*)nil)){
- X error("co failed");
- X continue;
- X }
- X if (!rev2) {
- X diffp[1] = workfilename;
- X if (workfilename[0] == '+') {
- X /* Some diffs have options with leading '+'. */
- X diffp[1] = argp =
- X ftnalloc(char, strlen(workfilename)+3);
- X *argp++ = '.';
- X *argp++ = SLASH;
- X VOID strcpy(argp, workfilename);
- X }
- X } else {
- X diffp[1] = maketemp(1);
- X diagnose("retrieving revision %s\n",xrev2);
- X bufscpy(&commarg, "-p");
- X bufscat(&commarg, xrev2);
- X if (run((char*)nil,diffp[1], co,quietarg,commarg.string,expandarg,versionarg,RCSfilename,(char *)nil)){
- X error("co failed");
- X continue;
- X }
- X }
- X if (!rev2)
- X diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workfilename);
- X else
- X diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
- X
- X exit_stats = runv(diffv);
- X
- X if (exit_stats)
- X if (WIFEXITED(exit_stats) && WEXITSTATUS(exit_stats)==1) {
- X if (!exitstatus)
- X exitstatus = 1;
- X } else
- X error("diff failed");
- X } while (cleanup(),
- X ++argv, --argc >=1);
- X
- X
- X tempunlink();
- X exitmain(exitstatus);
- X}
- X
- X static void
- Xcleanup()
- X{
- X if (nerror) exitstatus = EXIT_TROUBLE;
- X if (finptr) ffclose(finptr);
- X}
- X
- X#if lint
- X# define exiterr rdiffExit
- X#endif
- X exiting void
- Xexiterr()
- X{
- X tempunlink();
- X _exit(EXIT_TROUBLE);
- X}
- X
- X#if DIFF_L
- X static const char *
- Xsetup_label(b, name, date)
- X struct buf *b;
- X const char *name;
- X const char date[datesize];
- X{
- X const char *p;
- X
- X bufalloc(b, 2+strlen(name)+1+datesize);
- X for (p = date; *p++ != '.'; )
- X ;
- X VOID sprintf(b->string, "-L%s\t%s%.*s/%.2s/%.2s %.2s:%.2s:%s",
- X name,
- X date[2]=='.' ? "19" : "",
- X p-date-1, date, p, p+3, p+6, p+9, p+12
- X );
- X return b->string;
- X}
- X#endif
- END_OF_FILE
- if test 10976 -ne `wc -c <'src/rcsdiff.c'`; then
- echo shar: \"'src/rcsdiff.c'\" unpacked with wrong size!
- fi
- # end of 'src/rcsdiff.c'
- fi
- if test -f 'src/rcskeep.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/rcskeep.c'\"
- else
- echo shar: Extracting \"'src/rcskeep.c'\" \(9239 characters\)
- sed "s/^X//" >'src/rcskeep.c' <<'END_OF_FILE'
- X/*
- X * RCS keyword extraction
- X */
- X/*****************************************************************************
- X * main routine: getoldkeys()
- X * Testprogram: define KEEPTEST
- X *****************************************************************************
- X */
- X
- X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- X Copyright 1990 by Paul Eggert
- X Distributed under license by the Free Software Foundation, Inc.
- X
- XThis file is part of RCS.
- X
- XRCS is free software; you can redistribute it and/or modify
- Xit under the terms of the GNU General Public License as published by
- Xthe Free Software Foundation; either version 1, or (at your option)
- Xany later version.
- X
- XRCS is distributed in the hope that it will be useful,
- Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
- XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- XGNU General Public License for more details.
- X
- XYou should have received a copy of the GNU General Public License
- Xalong with RCS; see the file COPYING. If not, write to
- Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- X
- XReport problems and direct all questions to:
- X
- X rcs-bugs@cs.purdue.edu
- X
- X*/
- X
- X
- X
- X/* $Log: rcskeep.c,v $
- X * Revision 5.2 1990/10/04 06:30:20 eggert
- X * Parse time zone offsets; future RCS versions may output them.
- X *
- X * Revision 5.1 1990/09/20 02:38:56 eggert
- X * ci -k now checks dates more thoroughly.
- X *
- X * Revision 5.0 1990/08/22 08:12:53 eggert
- X * Retrieve old log message if there is one.
- X * Don't require final newline.
- X * Remove compile-time limits; use malloc instead. Tune.
- X * Permit dates past 1999/12/31. Ansify and Posixate.
- X *
- X * Revision 4.6 89/05/01 15:12:56 narten
- X * changed copyright header to reflect current distribution rules
- X *
- X * Revision 4.5 88/08/09 19:13:03 eggert
- X * Remove lint and speed up by making FILE *fp local, not global.
- X *
- X * Revision 4.4 87/12/18 11:44:21 narten
- X * more lint cleanups (Guy Harris)
- X *
- X * Revision 4.3 87/10/18 10:35:50 narten
- X * Updating version numbers. Changes relative to 1.1 actually relative
- X * to 4.1
- X *
- X * Revision 1.3 87/09/24 14:00:00 narten
- X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- X * warnings)
- X *
- X * Revision 1.2 87/03/27 14:22:29 jenkins
- X * Port to suns
- X *
- X * Revision 4.1 83/05/10 16:26:44 wft
- X * Added new markers Id and RCSfile; extraction added.
- X * Marker matching with trymatch().
- X *
- X * Revision 3.2 82/12/24 12:08:26 wft
- X * added missing #endif.
- X *
- X * Revision 3.1 82/12/04 13:22:41 wft
- X * Initial revision.
- X *
- X */
- X
- X/*
- X#define KEEPTEST
- X*/
- X/* Testprogram; prints out the keyword values found. */
- X
- X#include "rcsbase.h"
- X
- XlibId(keepId, "$Id: rcskeep.c,v 5.2 1990/10/04 06:30:20 eggert Exp $")
- X
- Xstatic int checknum P((const char*,int));
- Xstatic int getprevdate P((FILE*));
- Xstatic int getprevid P((int,FILE*,struct buf*));
- Xstatic int getprevrev P((FILE*));
- Xstatic int getval P((FILE*,struct buf*,int));
- Xstatic int get0val P((int,FILE*,struct buf*,int));
- X
- Xstruct buf prevauthor, prevrev, prevstate;
- Xchar prevdate[datesize];
- X
- X int
- Xgetoldkeys(fp)
- X register FILE *fp;
- X/* Function: Tries to read keyword values for author, date,
- X * revision number, and state out of the file fp.
- X * The results are placed into
- X * prevauthor, prevdate, prevrev, prevstate.
- X * Aborts immediately if it finds an error and returns false.
- X * If it returns true, it doesn't mean that any of the
- X * values were found; instead, check to see whether the corresponding arrays
- X * contain the empty string.
- X */
- X{
- X register int c;
- X char keyword[keylength+1];
- X register char * tp;
- X
- X /* initialize to empty */
- X bufscpy(&prevauthor, "");
- X bufscpy(&prevrev, "");
- X bufscpy(&prevstate, "");
- X *prevdate = 0;
- X
- X while( (c=getc(fp)) != EOF) {
- X if ( c==KDELIM) {
- X do {
- X /* try to get keyword */
- X tp = keyword;
- X while ((c=getc(fp))!=EOF && c!='\n' && c!=KDELIM && c!=VDELIM
- X && tp<keyword+keylength
- X )
- X *tp++ = c;
- X } while (c==KDELIM);
- X if (c==EOF)
- X break;
- X if (c!=VDELIM) continue;
- X *tp = c;
- X if ((c=getc(fp))!=' ' && c!='\t')
- X continue;
- X
- X switch (trymatch(keyword)) {
- X case Author:
- X if (!getprevid(0, fp, &prevauthor))
- X return false;
- X c = getc(fp);
- X break;
- X case Date:
- X if (!(c = getprevdate(fp)))
- X return false;
- X break;
- X case Header:
- X case Id:
- X if (!(
- X getval(fp, (struct buf*)nil, false) &&
- X getprevrev(fp) &&
- X (c = getprevdate(fp)) &&
- X getprevid(c, fp, &prevauthor) &&
- X getprevid(0, fp, &prevstate)
- X ))
- X return false;
- X /* Skip either ``who'' (new form) or ``Locker: who'' (old). */
- X if (getval(fp, (struct buf*)nil, true) &&
- X getval(fp, (struct buf*)nil, true))
- X c = getc(fp);
- X else if (nerror)
- X return false;
- X else
- X c = KDELIM;
- X break;
- X case Locker:
- X case Log:
- X case RCSfile:
- X case Source:
- X if (!getval(fp, (struct buf*)nil, false))
- X return false;
- X c = getc(fp);
- X break;
- X case Revision:
- X if (!getprevrev(fp))
- X return false;
- X c = getc(fp);
- X break;
- X case State:
- X if (!getprevid(0, fp, &prevstate))
- X return false;
- X c = getc(fp);
- X break;
- X default:
- X continue;
- X }
- X if (c != KDELIM) {
- X error("closing %c missing on keyword", KDELIM);
- X return false;
- X }
- X if (*prevauthor.string && *prevdate && *prevrev.string && *prevstate.string) {
- X break;
- X }
- X }
- X }
- X
- X arewind(fp);
- X return true;
- X}
- X
- X
- X static int
- Xgetval(fp, target, optional)
- X register FILE *fp;
- X struct buf *target;
- X int optional;
- X/* Reads a keyword value from FP into TARGET.
- X * Returns true if one is found, false otherwise.
- X * Does not modify target if it is nil.
- X * Do not report an error if OPTIONAL is set and KDELIM is found instead.
- X */
- X{
- X return get0val(getc(fp), fp, target, optional);
- X}
- X
- X static int
- Xget0val(c, fp, target, optional)
- X register int c;
- X register FILE *fp;
- X struct buf *target;
- X int optional;
- X/* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly.
- X * Same as getval, except C is the lookahead character.
- X */
- X{ register char * tp;
- X const char *tlim;
- X register int got1;
- X
- X if (target) {
- X bufalloc(target, 1);
- X tp = target->string;
- X tlim = tp + target->size;
- X } else
- X tlim = tp = 0;
- X got1 = false;
- X for (;; c = getc(fp))
- X switch (c) {
- X default:
- X got1 = true;
- X if (tp) {
- X *tp++ = c;
- X if (tlim <= tp)
- X tp = bufenlarge(target, &tlim);
- X }
- X continue;
- X
- X case ' ':
- X case '\t':
- X if (tp) {
- X *tp = 0;
- X# ifdef KEEPTEST
- X VOID printf("getval: %s\n", target);
- X# endif
- X }
- X if (!got1)
- X error("too much white space in keyword value");
- X return got1;
- X
- X case KDELIM:
- X if (!got1 && optional)
- X return false;
- X /* fall into */
- X case '\n':
- X case 0:
- X case EOF:
- X error("badly terminated keyword value");
- X return false;
- X }
- X}
- X
- X
- X static int
- Xgetprevdate(fp)
- XFILE *fp;
- X/* Function: reads a date prevdate; checks format
- X * Return 0 on error, lookahead character otherwise.
- X */
- X{
- X struct buf prevday, prevtime, prevzone, prev;
- X register const char *p;
- X register int c;
- X
- X c = 0;
- X bufautobegin(&prevday);
- X if (getval(fp,&prevday,false)) {
- X bufautobegin(&prevtime);
- X if (getval(fp,&prevtime,false)) {
- X bufautobegin(&prevzone);
- X bufscpy(&prevzone, "");
- X c = getc(fp);
- X if (c=='-' || c=='+')
- X c = get0val(c,fp,&prevzone,false) ? getc(fp) : 0;
- X if (c) {
- X bufautobegin(&prev);
- X p = prevday.string;
- X bufalloc(&prev, strlen(p) + strlen(prevtime.string) + strlen(prevzone.string) + 5);
- X VOID sprintf(prev.string, "%s%s %s %s",
- X /* Parse dates put out by old versions of RCS. */
- X isdigit(p[0]) && isdigit(p[1]) && p[2]=='/' ? "19" : "",
- X p, prevtime.string, prevzone.string
- X );
- X str2date(prev.string, prevdate);
- X bufautoend(&prev);
- X }
- X bufautoend(&prevzone);
- X }
- X bufautoend(&prevtime);
- X }
- X bufautoend(&prevday);
- X return c;
- X}
- X
- X static int
- Xgetprevid(c, fp, b)
- X int c;
- X FILE *fp;
- X struct buf *b;
- X/* Get previous identifier from C+FP into B. */
- X{
- X if (!get0val(c?c:getc(fp), fp, b, false))
- X return false;
- X checksid(b->string);
- X return true;
- X}
- X
- X static int
- Xgetprevrev(fp)
- X FILE *fp;
- X/* Get previous revision from FP into prevrev. */
- X{
- X return getval(fp,&prevrev,false) && checknum(prevrev.string,-1);
- X}
- X
- X
- X static int
- Xchecknum(sp,fields)
- X register const char *sp;
- X int fields;
- X{ register int dotcount;
- X dotcount=0;
- X while(*sp) {
- X if (*sp=='.') dotcount++;
- X else if (!isdigit(*sp)) return false;
- X sp++;
- X }
- X return fields<0 ? dotcount&1 : dotcount==fields;
- X}
- X
- X
- X
- X#ifdef KEEPTEST
- X
- Xconst char cmdid[] ="keeptest";
- X
- X int
- Xmain(argc, argv)
- Xint argc; char *argv[];
- X{
- X while (*(++argv)) {
- X FILE *f;
- X if (!(f = fopen(*argv,"r"))) {
- X perror(f);
- X exit(1);
- X }
- X getoldkeys(f);
- X VOID fclose(f);
- X VOID printf("%s: revision: %s, date: %s, author: %s, state: %s\n",
- X *argv, prevrev.string, prevdate.string, prevauthor.string, prevstate.string);
- X }
- X exitmain(EXIT_SUCCESS);
- X}
- X#endif
- END_OF_FILE
- if test 9239 -ne `wc -c <'src/rcskeep.c'`; then
- echo shar: \"'src/rcskeep.c'\" unpacked with wrong size!
- fi
- # end of 'src/rcskeep.c'
- fi
- if test -f 'src/rcsmerge.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/rcsmerge.c'\"
- else
- echo shar: Extracting \"'src/rcsmerge.c'\" \(7291 characters\)
- sed "s/^X//" >'src/rcsmerge.c' <<'END_OF_FILE'
- X/*
- X * rcsmerge operation
- X */
- X/*****************************************************************************
- X * join 2 revisions with respect to a third
- X *****************************************************************************
- X */
- X
- X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- X Copyright 1990 by Paul Eggert
- X Distributed under license by the Free Software Foundation, Inc.
- X
- XThis file is part of RCS.
- X
- XRCS is free software; you can redistribute it and/or modify
- Xit under the terms of the GNU General Public License as published by
- Xthe Free Software Foundation; either version 1, or (at your option)
- Xany later version.
- X
- XRCS is distributed in the hope that it will be useful,
- Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
- XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- XGNU General Public License for more details.
- X
- XYou should have received a copy of the GNU General Public License
- Xalong with RCS; see the file COPYING. If not, write to
- Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- X
- XReport problems and direct all questions to:
- X
- X rcs-bugs@cs.purdue.edu
- X
- X*/
- X
- X
- X
- X/* $Log: rcsmerge.c,v $
- X * Revision 5.3 1990/11/01 05:03:50 eggert
- X * Remove unneeded setid check.
- X *
- X * Revision 5.2 1990/09/04 08:02:28 eggert
- X * Check for I/O error when reading working file.
- X *
- X * Revision 5.1 1990/08/29 07:14:04 eggert
- X * Add -q. Pass -L options to merge.
- X *
- X * Revision 5.0 1990/08/22 08:13:41 eggert
- X * Propagate merge's exit status.
- X * Remove compile-time limits; use malloc instead.
- X * Make lock and temp files faster and safer. Ansify and Posixate. Add -V.
- X * Don't use access(). Tune.
- X *
- X * Revision 4.5 89/05/01 15:13:16 narten
- X * changed copyright header to reflect current distribution rules
- X *
- X * Revision 4.4 88/08/09 19:13:13 eggert
- X * Beware merging into a readonly file.
- X * Beware merging a revision to itself (no change).
- X * Use execv(), not system(); yield exit status like diff(1)'s.
- X *
- X * Revision 4.3 87/10/18 10:38:02 narten
- X * Updating version numbers. Changes relative to version 1.1
- X * actually relative to 4.1
- X *
- X * Revision 1.3 87/09/24 14:00:31 narten
- X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- X * warnings)
- X *
- X * Revision 1.2 87/03/27 14:22:36 jenkins
- X * Port to suns
- X *
- X * Revision 4.1 83/03/28 11:14:57 wft
- X * Added handling of default branch.
- X *
- X * Revision 3.3 82/12/24 15:29:00 wft
- X * Added call to catchsig().
- X *
- X * Revision 3.2 82/12/10 21:32:02 wft
- X * Replaced getdelta() with gettree(); improved error messages.
- X *
- X * Revision 3.1 82/11/28 19:27:44 wft
- X * Initial revision.
- X *
- X */
- X#include "rcsbase.h"
- X
- Xstatic exiting void nowork P((void));
- X
- Xstatic const char co[] = CO;
- X
- XmainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 5.3 1990/11/01 05:03:50 eggert Exp $")
- X{
- X static const char cmdusage[] =
- X "\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] [-p] [-Vn] file";
- X static const char quietarg[] = "-q";
- X
- X const char *rev1, *rev2; /*revision numbers*/
- X const char *temp1file, *temp2file;
- X const char *expandarg, *versionarg;
- X const char *mergearg[13], **a;
- X int tostdout;
- X int status, workfd;
- X struct buf commarg;
- X struct buf numericrev; /* holds expanded revision number */
- X struct hshentries *gendeltas; /* deltas to be generated */
- X struct hshentry * target;
- X
- X initid();
- X catchints();
- X
- X bufautobegin(&commarg);
- X bufautobegin(&numericrev);
- X rev1 = rev2 = nil;
- X status = 0; /* Keep lint happy. */
- X tostdout = false;
- X expandarg = versionarg = quietarg; /* i.e. a no-op */
- X
- X while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
- X switch ((*argv)[1]) {
- X case 'p':
- X tostdout=true;
- X goto revno;
- X case 'q':
- X quietflag = true;
- X /* falls into -r */
- X case 'r':
- X revno:
- X if ((*argv)[2]!='\0') {
- X if (!rev1)
- X rev1 = *argv + 2;
- X else if (!rev2)
- X rev2 = *argv + 2;
- X else
- X faterror("too many revision numbers");
- X } /* do nothing for empty -r or -p */
- X break;
- X case 'V':
- X versionarg = *argv;
- X setRCSversion(versionarg);
- X break;
- X
- X case 'k':
- X expandarg = *argv;
- X if (0 <= str2expmode(expandarg+2))
- X break;
- X /* fall into */
- X default:
- X faterror("unknown option: %s%s", *argv, cmdusage);
- X };
- X } /* end of option processing */
- X
- X if (argc<1) faterror("no input file%s", cmdusage);
- X if (!rev1) faterror("no base revision number given");
- X
- X /* now handle all filenames */
- X
- X if (pairfilenames(argc, argv, rcsreadopen, true, false) == 1) {
- X
- X if (argc>2 || (argc==2&&argv[1]!=nil))
- X warn("too many arguments");
- X diagnose("RCS file: %s\n", RCSfilename);
- X if ((workfd = open(workfilename, tostdout?O_RDONLY:O_RDWR)) < 0)
- X nowork();
- X
- X gettree(); /* reads in the delta tree */
- X
- X if (Head==nil) faterror("no revisions present");
- X
- X
- X if (!expandsym(rev1,&numericrev)) goto end;
- X if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end;
- X rev1=target->num;
- X if (!rev2)
- X rev2 = Dbranch ? Dbranch : Head->num;
- X if (!expandsym(rev2,&numericrev)) goto end;
- X if (!(target=genrevs(numericrev.string, (char *)nil, (char *)nil, (char *)nil,&gendeltas))) goto end;
- X rev2=target->num;
- X
- X if (strcmp(rev1,rev2) == 0) {
- X error("merging revision %s to itself (no change)",
- X rev1
- X );
- X if (tostdout) {
- X FILE *w;
- X errno = 0;
- X if (!(w = fdopen(workfd,"r")))
- X nowork();
- X fastcopy(w,stdout);
- X ffclose(w);
- X }
- X goto end;
- X }
- X if (close(workfd) < 0)
- X nowork();
- X
- X temp1file = maketemp(0);
- X temp2file = maketemp(1);
- X
- X diagnose("retrieving revision %s\n", rev1);
- X bufscpy(&commarg, "-p");
- X bufscat(&commarg, rev1);
- X if (run((char*)nil,temp1file, co,quietarg,commarg.string,expandarg,versionarg,RCSfilename,(char*)nil)){
- X faterror("co failed");
- X }
- X diagnose("retrieving revision %s\n",rev2);
- X bufscpy(&commarg, "-p");
- X bufscat(&commarg, rev2);
- X if (run((char*)nil,temp2file, co,quietarg,commarg.string,expandarg,versionarg,RCSfilename,(char*)nil)){
- X faterror("co failed");
- X }
- X diagnose("Merging differences between %s and %s into %s%s\n",
- X rev1, rev2, workfilename,
- X tostdout?"; result to stdout":"");
- X
- X a = mergearg;
- X *a++ = nil;
- X *a++ = nil;
- X *a++ = MERGE;
- X if (tostdout)
- X *a++ = "-p";
- X if (quietflag)
- X *a++ = quietarg;
- X *a++ = "-L"; *a++ = workfilename;
- X *a++ = "-L"; *a++ = rev2;
- X *a++ = workfilename;
- X *a++ = temp1file;
- X *a++ = temp2file;
- X *a = nil;
- X
- X status = runv(mergearg);
- X if (!WIFEXITED(status) || 1 < WEXITSTATUS(status)) {
- X faterror("merge failed");
- X }
- X }
- X
- Xend:
- X tempunlink();
- X exitmain(nerror ? EXIT_TROUBLE : WEXITSTATUS(status));
- X}
- X
- X#if lint
- X# define exiterr rmergeExit
- X#endif
- X exiting void
- Xexiterr()
- X{
- X tempunlink();
- X _exit(EXIT_TROUBLE);
- X}
- X
- X
- X static exiting void
- Xnowork()
- X{
- X efaterror(workfilename);
- X}
- END_OF_FILE
- if test 7291 -ne `wc -c <'src/rcsmerge.c'`; then
- echo shar: \"'src/rcsmerge.c'\" unpacked with wrong size!
- fi
- # end of 'src/rcsmerge.c'
- fi
- echo shar: End of archive 10 \(of 12\).
- cp /dev/null ark10isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 12 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-